package org.vectrics.company;


import java.math.BigDecimal;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;

import org.vectrics.SystemException;
import org.vectrics.common.db.Auditable;
import org.vectrics.common.util.DateSync;
import org.vectrics.hibernate.ThreadProperties;
import org.vectrics.provider.CoreServiceLocator;
import org.vectrics.user.Person;

/**
 * Class that associates a person with a company - this could be an 
 * employee of a company or some other association that is defined by the roles
 * container (CompanyPersonRole)
 * @author Mike Moore
 *
 */
public class CompanyPerson implements Auditable {
	private Long id = null;
	private Person person = null;
	private Company company = null;
	private Date dateStart = DateSync.getCurrentTime();
	private Date dateEnd = null;
	private Date dateStartScheduled = null;
	private Date dateEndScheduled = null;
	private Set roles = new HashSet();
	private BigDecimal salary = null;
	private SalaryType salaryType = null;
	private Person createdBy = null;
	private Date createdDate = null;
	private Person lastModifiedBy = null;
	private Date lastModifiedDate = null;
	private boolean voided = false;
	
	public CompanyPerson() {
		super();
	}
	
	/**
	 * @return Returns the title.
	 */
	public String getTitle() {
		String title = null;
		if (this.getRoles() != null) {
			CompanyPersonRole lastRole = getLastRole();
			if (lastRole != null) {
				title = lastRole.getTitle();
			}
		}
		return(title);
	}
	
	public CompanyPersonRole getCurrentRole() {
		Iterator iter = this.getRoles().iterator();
		CompanyPersonRole current = null;
		while (iter.hasNext()) {
			CompanyPersonRole role = (CompanyPersonRole)iter.next();
			if (role.getDateEnd() == null) {
				current = role;
				break;
			}
		}
		return(current);
	}
	
	public CompanyPersonRole getLastRole() {
		Date maxDate = new Date(0);
		Iterator iter = this.getRoles().iterator();
		CompanyPersonRole current = null;
		while (iter.hasNext()) {
			CompanyPersonRole role = (CompanyPersonRole)iter.next();
			if ((role.getDateEnd() == null) || (role.getDateEnd().after(maxDate))) {
				current = role;
			}
		}
		return(current);
	}


	/**
	 * @return Returns the id.
	 */
	public Long getId() {
		return id;
	}

	/**
	 * @param id The id to set.
	 */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * @return Returns the dateEnd.
	 */
	public Date getDateEnd() {
		return dateEnd;
	}

	/**
	 * @param dateEnd The dateEnd to set.
	 */
	public void setDateEnd(Date dateEnd) {
		this.dateEnd = dateEnd;
	}

	/**
	 * @return Returns the dateStart.
	 */
	public Date getDateStart() {
		return dateStart;
	}

	/**
	 * @param dateStart The dateStart to set.
	 */
	public void setDateStart(Date dateStart) {
		this.dateStart = dateStart;
	}

	/**
	 * @return Returns the person.
	 */
	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}
	
	public void setCompany(Company company) {
		this.company = company;
	}
	
	public Company getCompany() {
		return(company);
	}

	public void addRole(CompanyPersonRole role) {
		this.roles.add(role);
		role.setPerson(this.getPerson());
		role.setCompanyPerson(this);
	}
	
	public CompanyPersonRole addRole(CompanyPersonRoleType roleType, Date startDate) {
		if (roleType == null)
			throw new SystemException("addRole() was passed a null roletype");
	    closeLastRole(startDate);
	    CompanyPersonRole companyPersonRole = findRole(roleType);
	    if (companyPersonRole == null) {
	    	Locale locale = ThreadProperties.getPerson().getLocale().getJavaLocale();
	        companyPersonRole = new CompanyPersonRole();
	        companyPersonRole.setRoleType(roleType);
	        if (person == null)
	        	throw new SystemException("Adding company person role cannot be done before assigning a person");
	        if (person.getId() == null)
	        	throw new SystemException("Adding company person role cannot be done before saving person (person id is null)");
	        companyPersonRole.setPerson(this.person);
	        companyPersonRole.setDateStart(startDate);
	        companyPersonRole.setDateEnd(null);
	        companyPersonRole.setTitle(CoreServiceLocator.getPhraseProvider().getMessage(roleType.getDescriptionCode(), locale));
	        if (companyPersonRole.getTitle().length() > CompanyPersonRole.MAX_LENGTH_TITLE) {
	        	companyPersonRole.setTitle(companyPersonRole.getTitle().substring(0, CompanyPersonRole.MAX_LENGTH_TITLE));
	        }
	        this.roles.add(companyPersonRole);
			companyPersonRole.setCompanyPerson(this);
	    }
	    return(companyPersonRole);
	}

	
	public void closeLastRole(Date closeDate) {
	    Iterator iter = this.getRoles().iterator();
	    while (iter.hasNext()) {
	        CompanyPersonRole role = (CompanyPersonRole)iter.next();
	        if (role.getDateEnd() == null) {
	            role.setDateEnd(closeDate);
	        }
	    }
	}
	
	public CompanyPersonRole findRole(CompanyPersonRoleType role) {
		if (role == null)
			throw new SystemException("findRole(role) was passed a null role");
	    CompanyPersonRole found = null;
	    Iterator iter = this.roles.iterator();
	    while (iter.hasNext()) {
	        CompanyPersonRole companyPersonRole = (CompanyPersonRole)iter.next();
	        CompanyPersonRoleType roleType = (CompanyPersonRoleType)companyPersonRole.getRoleType();
	        if (roleType.getCode().equals(role.getCode())) {
	            found = companyPersonRole;
	        }
	    }
	    return(found);
	}

	
	public CompanyPersonRole findRole(Long roleId) {
	    CompanyPersonRole found = null;
	    Iterator iter = this.roles.iterator();
	    while (iter.hasNext()) {
	        CompanyPersonRole companyPersonRole = (CompanyPersonRole)iter.next();
	        if (companyPersonRole.getId().equals(roleId)) {
	            found = companyPersonRole;
	        }
	    }
	    return(found);
	}
	
	
	/**
     * @return Returns the role.
     */
    public Set getRoles() {
        return roles;
    }
    /**
     * @param role The role to set.
     */
    public void setRoles(Set roles) {
        this.roles = roles;
    }
    
    
	/**
	 * @return Returns the dateEndScheduled.
	 */
	public Date getDateEndScheduled() {
		return dateEndScheduled;
	}
	/**
	 * @param dateEndScheduled The dateEndScheduled to set.
	 */
	public void setDateEndScheduled(Date dateEndScheduled) {
		this.dateEndScheduled = dateEndScheduled;
	}
	/**
	 * @return Returns the dateStartScheduled.
	 */
	public Date getDateStartScheduled() {
		return dateStartScheduled;
	}
	/**
	 * @param dateStartScheduled The dateStartScheduled to set.
	 */
	public void setDateStartScheduled(Date dateStartScheduled) {
		this.dateStartScheduled = dateStartScheduled;
	}
	/**
	 * @return Returns the salary.
	 */
	public BigDecimal getSalary() {
		return salary;
	}
	/**
	 * @param salary The salary to set.
	 */
	public void setSalary(BigDecimal salary) {
		this.salary = salary;
	}
	/**
	 * @return Returns the salaryType.
	 */
	public SalaryType getSalaryType() {
		return salaryType;
	}
	/**
	 * @param salaryType The salaryType to set.
	 */
	public void setSalaryType(SalaryType salaryType) {
		this.salaryType = salaryType;
	}
	
	
	/**
	 * @return Returns the voided.
	 */
	public boolean getVoided() {
		return voided;
	}
	/**
	 * @param voided The voided to set.
	 */
	public void setVoided(boolean voided) {
		this.voided = voided;
	}

	/**
	 * @return Returns the createdBy.
	 */
	public Person getCreatedBy() {
		return createdBy;
	}

	/**
	 * @param createdBy The createdBy to set.
	 */
	public void setCreatedBy(Person createdBy) {
		this.createdBy = createdBy;
	}

	/**
	 * @return Returns the createdDate.
	 */
	public Date getCreatedDate() {
		return createdDate;
	}

	/**
	 * @param createdDate The createdDate to set.
	 */
	public void setCreatedDate(Date createdDate) {
		this.createdDate = createdDate;
	}

	/**
	 * @return Returns the lastModifiedBy.
	 */
	public Person getLastModifiedBy() {
		return lastModifiedBy;
	}

	/**
	 * @param lastModifiedBy The lastModifiedBy to set.
	 */
	public void setLastModifiedBy(Person lastModifiedBy) {
		this.lastModifiedBy = lastModifiedBy;
	}

	/**
	 * @return Returns the lastModifiedDate.
	 */
	public Date getLastModifiedDate() {
		return lastModifiedDate;
	}

	/**
	 * @param lastModifiedDate The lastModifiedDate to set.
	 */
	public void setLastModifiedDate(Date lastModifiedDate) {
		this.lastModifiedDate = lastModifiedDate;
	}

	public boolean logEntityChanges() {
		return(true);
	}
	
}
